﻿/*
DotNetMQ - A Complete Message Broker For .NET
Copyright (C) 2011 Halil ibrahim KALKAN

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

using ELab.Communication.Messages.ControllerMessages;
using ELab.Exceptions;
using ELab.Management;
using ELab.Serialization.Data;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace ELab.Teacher
{
    public partial class SurveysForm : Form
    {
        #region Private fields
        /// <summary>
        /// Reference to ELabController object.
        /// All communication with ELab server is performed using this object.
        /// </summary>
        private readonly ELabController _controller;

        /// <summary>
        /// This list is used as DataSource of data grid.
        /// It stores client applications.
        /// </summary>
        private readonly List<Survey> _surveysList;

        /// <summary>
        /// This list is used to set data grid's datasource to clear items.
        /// </summary>
        private readonly List<Survey> _emptyList;
        #endregion

        #region Constructor

        /// <summary>
        /// Creates a new ApplicationListForm object.
        /// </summary>
        /// <param name="controller">Reference to ELabController object</param>
        public SurveysForm(ELabController controller)
        {
            _controller = controller;
            if (_controller != null)
            {
                _controller.Disconnect();
                _controller.Connect();
            }
            _surveysList = new List<Survey>();
            _emptyList = new List<Survey>();
            InitializeComponent();
            gwUserList.AutoGenerateColumns = false;
        }

        #endregion

        #region Public methods
        /// <summary>
        /// This method is called by MainForm when a ClientApplicationRemovedEventMessage received from ELab Server.
        /// </summary>
        /// <param name="message"></param>
        public void GetClientApplicationRemovedEventMessage(int message)
        {
            lock (_surveysList)
            {
                RemoveSurveyFromList(message);
            }
        }

        #endregion

        #region Private methods

        #region Form events

        private void ApplicationList_Load(object sender, EventArgs e)
        {
            PrepareForm();
            GetSurveysServer();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            var addSurveyForm = new NewSurveyForm();
            addSurveyForm.ShowDialog();
            if (string.IsNullOrEmpty(addSurveyForm.Question))
            {
                return;
            }
            try
            {
                _controller.SendMessage(new AddNewSurveyMessage
                {
                    Survey = new Survey
                    {
                        Question = addSurveyForm.Question,
                    }
                });
                GetSurveysServer();
            }
            catch (Exception ex)
            {
                //Logger.Error(ex.Message, ex);
                MessageBox.Show("Survey can not be added. Detail: " + ex.Message, "Error!");
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            lock (_surveysList)
            {
                //Check if user selected any application to remove
                if (gwUserList.SelectedRows.Count <= 0)
                {
                    return;
                }

                var selectedIndex = gwUserList.SelectedRows[0].Index;
                if ((selectedIndex < 0) || (selectedIndex >= _surveysList.Count))
                {
                    return;
                }

                //Get confirmation from user to remove application.
                var idSurvey = _surveysList[selectedIndex].ID;
                var dialogResult =
                    MessageBox.Show("Are you sure to remove '" + idSurvey + "' survey from ELab",
                                                    "Attention! You are removing an user", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dialogResult != DialogResult.Yes)
                {
                    return;
                }

                try
                {
                    //Send RemoveApplicationMessage to ELab server
                    var message = _controller.SendMessageAndGetResponse(new RemoveSurveyMessage { ID = idSurvey });

                    //Check response message
                    if (message.MessageTypeId != ControlMessageFactory.MessageTypeIdGeneralResponseMessage)
                    {
                        throw new ELabException("Response message to RemoveSurveyMessage must be as SurveyResponseMessage");
                    }

                    var responseMessage = message as GeneralResponseMessage;
                    if (responseMessage == null)
                    {
                        throw new ELabException("Incorrect type. MessageTypeId = " + message.MessageTypeId + ", but Type of object: " + message.GetType().Name);
                    }

                    //Evaluate response message
                    if (responseMessage.IsSuccess)
                    {
                        RemoveSurveyFromList(idSurvey);
                    }
                    else
                    {
                        MessageBox.Show(idSurvey + " Survey can not be removed!", responseMessage.ResultMessage, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                    }
                }
                catch (Exception ex)
                {
                    //Logger.Error(ex.Message, ex);
                    MessageBox.Show(idSurvey + " Survey can not be removed. Detail: " + ex.Message, "Error!");
                }
            }
        }

        private void btnRefreshList_Click(object sender, EventArgs e)
        {
            GetSurveysServer();
        }

        private void editWebServicesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int applicationName;
            lock (_surveysList)
            {
                //Check if user selected any application to remove
                if (gwUserList.SelectedRows.Count <= 0)
                {
                    return;
                }

                var selectedIndex = gwUserList.SelectedRows[0].Index;
                if ((selectedIndex < 0) || (selectedIndex >= _surveysList.Count))
                {
                    return;
                }

                //Get confirmation from user to remove application.
                applicationName = _surveysList[selectedIndex].ID;
            }

            //var editWebServiceForm = new EditApplicationWebServicesForm(_controller, applicationName);
            //editWebServiceForm.ShowDialog();
        }

        #endregion

        #region Other private methods

        /// <summary>
        /// Gets all applications from server and fills into list.
        /// </summary>
        private void GetSurveysServer()
        {
            try
            {
                //Send a message to ELab server to get list of client applications, get response and fill data grid.
                var message = _controller.SendMessageAndGetResponse(new GetSurveysMessage());
                if (message.MessageTypeId != ControlMessageFactory.MessageTypeIdGetSurveysResponseMessage)
                {
                    throw new ELabException("Response message to GetSurveysMessage must be a GetSurveysResponseMessage");
                }

                var surveysListMessage = message as GetSurveysResponseMessage;
                if (surveysListMessage == null)
                {
                    throw new ELabException("Incorrect message type. MessageTypeId = " + message.MessageTypeId + ", but Type of object: " + message.GetType().Name);
                }

                FillSurveysList(surveysListMessage.Surveys);
            }
            catch (Exception ex)
            {
                //Logger.Error(ex.Message, ex);
                MessageBox.Show("Surveys list can not received from ELab Server. Detail: " + ex.Message, "Error!");
            }
        }

        /// <summary>
        /// Fills data grid (gwApplicationList) by list of applications.
        /// </summary>
        /// <param name="surveys">Application list</param>
        private void FillSurveysList(IEnumerable<Survey> surveys)
        {
            lock (_surveysList)
            {
                EmptyList();
                _surveysList.Clear();
                foreach (var survey in surveys)
                {
                    _surveysList.Add(survey);
                }
                RefreshList();
            }
        }

        /// <summary>
        /// Removes application from shown application list.
        /// </summary>
        /// <param name="id">Name of the application</param>
        private void RemoveSurveyFromList(int id)
        {
            //Find application in list
            Survey survey = null;
            foreach (var surveyItem in _surveysList)
            {
                if (id.Equals(surveyItem.ID))
                {
                    survey = surveyItem;
                    break;
                }
            }

            //No action if application is not in list.
            if (survey == null)
            {
                return;
            }

            EmptyList();
            _surveysList.Remove(survey);
            RefreshList();
        }

        /// <summary>
        /// Empties data grid.
        /// </summary>
        private void EmptyList()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(EmptyList));
            }
            else
            {
                gwUserList.DataSource = _emptyList;
            }
        }

        /// <summary>
        /// Refreshes data grid.
        /// </summary>
        private void RefreshList()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(RefreshList));
            }
            else
            {
                gwUserList.DataSource = _emptyList;
                gwUserList.DataSource = _surveysList;
            }
        }

        /// <summary>
        /// Prepares form. This method is called while form is opening.
        /// </summary>
        private void PrepareForm()
        {
            Left = (Screen.GetWorkingArea(this).Width - Width) / 2;
            Top = (Screen.GetWorkingArea(this).Height - Height) / 2;
        }

        #endregion

        #endregion

        private void SurveysForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_controller != null) _controller.Disconnect();
        }
    }
}
